import requests
import hmac
import hashlib
import base64
import time
import json
from pathlib import Path
from typing import Dict, Any, Optional, List
from urllib.parse import quote_plus
from .base_sender import BaseReportSender

class DingTalkSender(BaseReportSender):
    """钉钉发送器"""
    
    def __init__(self, config: Dict[str, Any]):
        """初始化钉钉发送器
        
        Args:
            config: 钉钉配置信息，包含以下字段：
                - webhook: 钉钉机器人webhook地址
                - secret: 钉钉机器人加签密钥（可选）
                - at_mobiles: 需要@的手机号列表（可选）
                - at_user_ids: 需要@的用户ID列表（可选）
                - is_at_all: 是否@所有人（可选）
        """
        super().__init__(config)
        self.required_keys = ['webhook']
        
    def send_report(self, report_path: Path, title: str, content: Optional[str] = None) -> bool:
        """发送测试报告到钉钉
        
        Args:
            report_path: 报告文件路径
            title: 消息标题
            content: 消息内容（可选）
            
        Returns:
            是否发送成功
        """
        if not self._validate_config(self.required_keys):
            return False
            
        try:
            # 获取文件信息
            file_info = self._get_file_info(report_path)
            
            # 构建消息内容
            message = {
                "msgtype": "markdown",
                "markdown": {
                    "title": title,
                    "text": self._build_message_text(title, content, file_info)
                }
            }
            
            # 添加@信息
            self._add_at_info(message)
            
            # 发送消息
            return self._retry_on_failure(self._send_message, message)
            
        except Exception as e:
            self.logger.error(f"Failed to send test report to DingTalk: {str(e)}")
            return False
            
    def _build_message_text(self, title: str, content: Optional[str], file_info: Dict[str, Any]) -> str:
        """构建消息文本
        
        Args:
            title: 消息标题
            content: 消息内容
            file_info: 文件信息
            
        Returns:
            消息文本
        """
        text = f"### {title}\n\n"
        
        if content:
            text += f"{content}\n\n"
            
        if file_info:
            text += "#### 报告信息\n"
            text += f"- 文件大小：{file_info['size']}\n"
            text += f"- 修改时间：{file_info['modified_time']}\n"
            text += f"- 文件哈希：{file_info['hash']}\n\n"
            
        # 添加报告链接（这里假设报告已经上传到某个可访问的URL）
        report_url = self._upload_report(report_path)
        if report_url:
            text += f"[查看测试报告]({report_url})"
            
        return text
        
    def _add_at_info(self, message: Dict[str, Any]):
        """添加@信息
        
        Args:
            message: 消息对象
        """
        at = {}
        
        # 添加@手机号
        if 'at_mobiles' in self.config:
            at['atMobiles'] = self.config['at_mobiles']
            
        # 添加@用户ID
        if 'at_user_ids' in self.config:
            at['atUserIds'] = self.config['at_user_ids']
            
        # 添加@所有人
        if self.config.get('is_at_all'):
            at['isAtAll'] = True
            
        if at:
            message['at'] = at
            
    def _send_message(self, message: Dict[str, Any]) -> bool:
        """发送消息
        
        Args:
            message: 消息对象
            
        Returns:
            是否发送成功
        """
        # 添加时间戳和签名
        timestamp = str(round(time.time() * 1000))
        if 'secret' in self.config:
            secret = self.config['secret']
            string_to_sign = f"{timestamp}\n{secret}"
            hmac_code = hmac.new(
                secret.encode('utf-8'),
                string_to_sign.encode('utf-8'),
                digestmod=hashlib.sha256
            ).digest()
            sign = quote_plus(base64.b64encode(hmac_code))
            webhook = f"{self.config['webhook']}&timestamp={timestamp}&sign={sign}"
        else:
            webhook = self.config['webhook']
            
        response = requests.post(webhook, json=message)
        response.raise_for_status()
        result = response.json()
        
        if result.get('errcode') == 0:
            self.logger.info("Successfully sent test report to DingTalk")
            return True
        else:
            self.logger.error(f"Failed to send test report to DingTalk: {result.get('errmsg')}")
            return False
            
    def _upload_report(self, report_path: Path) -> Optional[str]:
        """上传报告文件并返回URL
        
        Args:
            report_path: 报告文件路径
            
        Returns:
            报告文件URL
        """
        # TODO: 实现文件上传逻辑，返回可访问的URL
        # 这里需要根据实际情况实现，比如上传到对象存储服务
        return None 